From a5e017883cd28c2aa48ea6f1e2b1e89ca4f20e58 Mon Sep 17 00:00:00 2001 From: "kaf24@freefall.cl.cam.ac.uk" Date: Wed, 20 Oct 2004 08:12:06 +0000 Subject: [PATCH] bitkeeper revision 1.1159.1.243 (41761dd6FhmRMJyuSuwaKjjF1oicDQ) Fix GDT checking so that we check ownership before zapping reserved entries (bug pointed out by Michael Vrable). Also map_domain_mem() isn't used across a 'goto fail' any more, so the error-exit path is now correct. --- xen/arch/x86/x86_32/mm.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/xen/arch/x86/x86_32/mm.c b/xen/arch/x86/x86_32/mm.c index 420c3bde5c..40acc39c81 100644 --- a/xen/arch/x86/x86_32/mm.c +++ b/xen/arch/x86/x86_32/mm.c @@ -259,23 +259,39 @@ long set_gdt(struct domain *d, unsigned int entries) { /* NB. There are 512 8-byte entries per GDT page. */ - int i, nr_pages = (entries + 511) / 512; + int i = 0, nr_pages = (entries + 511) / 512; struct desc_struct *vgdt; + unsigned long pfn; - vgdt = map_domain_mem(frames[0] << PAGE_SHIFT); - memset( vgdt + FIRST_RESERVED_GDT_ENTRY, 0, - NR_RESERVED_GDT_ENTRIES*8); + /* Check the first page in the new GDT. */ + if ( (pfn = frames[0]) >= max_page ) + goto fail; - /* Check the new GDT. */ - for ( i = 0; i < nr_pages; i++ ) + /* The first page is special because Xen owns a range of entries in it. */ + if ( !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) ) { - if ( unlikely(frames[i] >= max_page) || - unlikely(!get_page_and_type(&frame_table[frames[i]], - d, PGT_gdt_page)) ) + /* GDT checks failed: try zapping the Xen reserved entries. */ + if ( !get_page_and_type(&frame_table[pfn], d, PGT_writable_page) ) + goto fail; + vgdt = map_domain_mem(pfn << PAGE_SHIFT); + memset(vgdt + FIRST_RESERVED_GDT_ENTRY, 0, + NR_RESERVED_GDT_ENTRIES*8); + unmap_domain_mem(vgdt); + put_page_and_type(&frame_table[pfn]); + + /* Okay, we zapped the entries. Now try the GDT checks again. */ + if ( !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) ) goto fail; } + /* Check the remaining pages in the new GDT. */ + for ( i = 1; i < nr_pages; i++ ) + if ( ((pfn = frames[i]) >= max_page) || + !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) ) + goto fail; + /* Copy reserved GDT entries to the new GDT. */ + vgdt = map_domain_mem(frames[0] << PAGE_SHIFT); memcpy(vgdt + FIRST_RESERVED_GDT_ENTRY, gdt_table + FIRST_RESERVED_GDT_ENTRY, NR_RESERVED_GDT_ENTRIES*8); -- 2.30.2